home *** CD-ROM | disk | FTP | other *** search
/ Sounds Terrific 2 / Sounds Terrific II (1996)(Weird Science)(Disc 1 of 2)[Amiga-PC].iso / archives / amiga / amisox33.lha / AmiSOX3.3 / dist / wav.c < prev    next >
C/C++ Source or Header  |  1994-01-23  |  6KB  |  235 lines

  1. /*
  2.  * April 15, 1992
  3.  * Copyright 1992 Rick Richardson
  4.  * Copyright 1991 Lance Norskog And Sundry Contributors
  5.  * This source code is freely redistributable and may be used for
  6.  * any purpose.  This copyright notice must be maintained. 
  7.  * Lance Norskog And Sundry Contributors are not responsible for 
  8.  * the consequences of using this software.
  9.  */
  10.  
  11. /*
  12.  * Windows 3.0 .wav format driver
  13.  */
  14.  
  15. /*
  16.  * Fixed by various contributors:
  17.  * 1) Little-endian handling
  18.  * 2) Skip other kinds of file data
  19.  * 3) Handle 16-bit formats correctly
  20.  * 4) Not go into infinite loop
  21.  */
  22.  
  23. #include "st.h"
  24. #include "wav.h"
  25.  
  26. /* Private data for .wav file */
  27. typedef struct wavstuff {
  28.     long    samples;
  29. } *wav_t;
  30.  
  31. IMPORT float volume, amplitude;
  32. IMPORT long summary, verbose;
  33.  
  34. /*
  35.  * Do anything required before you start reading samples.
  36.  * Read file header. 
  37.  *    Find out sampling rate, 
  38.  *    size and style of samples, 
  39.  *    mono/stereo/quad.
  40.  */
  41. wavstartread(ft) 
  42. ft_t ft;
  43. {
  44.     wav_t    wav = (wav_t) ft->priv;
  45.     char    magic[4];
  46.     long    len;
  47.     int    littlendian = 1;
  48.     char    *endptr;
  49.     char    c;
  50.  
  51.     endptr = (char *) &littlendian;
  52.     if (!*endptr) ft->swap = 1;
  53.  
  54.     /* If you need to seek around the input file. */
  55.     if (0 && ! ft->seekable)
  56.         fail("Sorry, .wav input file must be a file, not a pipe");
  57.  
  58.     fread(magic, 4, 1, ft->fp);
  59.     if (strncmp("RIFF", magic, 4))
  60.         fail("Sorry, not a RIFF file");
  61.  
  62.     len = rllong(ft);
  63.  
  64.     fread(magic, 4, 1, ft->fp);
  65.     if (strncmp("WAVE", magic, 4))
  66.         fail("Sorry, not a WAVE file");
  67.  
  68.     /* Skip to the next "fmt " or end of file */
  69.     while(1) {
  70.         if (feof(ft->fp))
  71.             fail("Sorry, missing fmt spec");
  72.         fread(magic, 4, 1, ft->fp);
  73.         if (! strncmp("fmt ", magic, 4))
  74.             break;
  75.         for (len = rllong(ft); len>0; len--)
  76.             fread(&c,1,1,ft->fp);
  77.     }
  78.  
  79.     len = rllong(ft);
  80.     switch (rlshort(ft))
  81.     {
  82.         case WAVE_FORMAT_UNKNOWN:
  83.         fail("Sorry, this WAV file is in Microsoft Official Unknown format.");
  84.         case WAVE_FORMAT_PCM:     /* this one, at least, I can handle */
  85.             break;
  86.         case WAVE_FORMAT_ADPCM:
  87.         fail("Sorry, this WAV file is in Microsoft ADPCM format.");
  88.         case WAVE_FORMAT_ALAW:
  89.         fail("Sorry, this WAV file is in Microsoft A-law format.");
  90.         case WAVE_FORMAT_MULAW:
  91.         fail("Sorry, this WAV file is in Microsoft U-law format.");
  92.         case WAVE_FORMAT_OKI_ADPCM:
  93.         fail("Sorry, this WAV file is in OKI ADPCM format.");
  94.         case WAVE_FORMAT_DIGISTD:
  95.         fail("Sorry, this WAV file is in Digistd format.");
  96.         case WAVE_FORMAT_DIGIFIX:
  97.         fail("Sorry, this WAV file is in Digifix format.");
  98.         case IBM_FORMAT_MULAW:
  99.         fail("Sorry, this WAV file is in IBM U-law format.");
  100.         case IBM_FORMAT_ALAW:
  101.         fail("Sorry, this WAV file is in IBM A-law format.");
  102.         case IBM_FORMAT_ADPCM:
  103.         fail("Sorry, this WAV file is in IBM ADPCM format.");
  104.     default:    fail("Sorry, don't understand format");
  105.     }
  106.     ft->info.channels = rlshort(ft);
  107.     ft->info.rate = rllong(ft);
  108.     rllong(ft);    /* Average bytes/second */
  109.     rlshort(ft);    /* Block align */
  110.     switch (rlshort(ft))
  111.     {
  112.     case 8:        ft->info.size = BYTE; ft->info.style = UNSIGNED; break;
  113.     case 16:    ft->info.size = WORD; ft->info.style = SIGN2; break;
  114.     case 32:    ft->info.size = LONG; ft->info.style = SIGN2; break;
  115.     default:    fail("Sorry, don't understand size");
  116.     }
  117.     len -= 16;
  118.     while (--len >= 0) getc(ft->fp);
  119.  
  120.     fread(magic, 4, 1, ft->fp);
  121.     if (strncmp("data", magic, 4))
  122.         fail("Sorry, missing data portion");
  123.  
  124.     wav->samples = rllong(ft) / ft->info.size;
  125. }
  126.  
  127. /*
  128.  * Read up to len samples from file.
  129.  * Convert to signed longs.
  130.  * Place in buf[].
  131.  * Return number of samples read.
  132.  */
  133.  
  134. wavread(ft, buf, len) 
  135. ft_t ft;
  136. long *buf, len;
  137. {
  138.     wav_t    wav = (wav_t) ft->priv;
  139.     int    done;
  140.  
  141.     if (len > wav->samples) len = wav->samples;
  142.     if (len == 0) return 0;
  143.     done = rawread(ft, buf, len);
  144.     if (done == 0) report("Premature EOF on .wav input file");
  145.     wav->samples -= done;
  146.     return done;
  147. }
  148.  
  149. /*
  150.  * Do anything required when you stop reading samples.  
  151.  * Don't close input file! 
  152.  */
  153. wavstopread(ft) 
  154. ft_t ft;
  155. {
  156. }
  157.  
  158. wavstartwrite(ft) 
  159. ft_t ft;
  160. {
  161.     wav_t    wav = (wav_t) ft->priv;
  162.     int    littlendian = 1;
  163.     char    *endptr;
  164.  
  165.     if (! ft->seekable)
  166.         fail("Sorry, output .wav file must be a file, not a pipe");
  167.  
  168.     endptr = (char *) &littlendian;
  169.     if (!*endptr) ft->swap = 1;
  170.  
  171.     wav->samples = 0;
  172.     wavwritehdr(ft);
  173. }
  174.  
  175. wavwritehdr(ft) 
  176. ft_t ft;
  177. {
  178.     wav_t    wav = (wav_t) ft->priv;
  179.     int    samsize;
  180.     long    datasize;
  181.  
  182.     switch (ft->info.size)
  183.     {
  184.     case BYTE:    samsize = 8; ft->info.style = UNSIGNED; break;
  185.     case WORD:    samsize = 16; ft->info.style = SIGN2; break;
  186.     default:
  187.     case LONG:    ft->info.size = LONG; ft->info.style = SIGN2; 
  188.             samsize = 32; break;
  189.     }
  190.     
  191.  
  192.     datasize = ft->info.size * wav->samples;
  193.  
  194.     fputs("RIFF", ft->fp);
  195.     wllong(ft, datasize + 8+16+12);    /* Waveform chunk size: FIXUP(4) */
  196.     fputs("WAVE", ft->fp);
  197.     fputs("fmt ", ft->fp);
  198.     wllong(ft, (long)16);        /* fmt chunk size */
  199.     wlshort(ft, 1);            /* FormatTag: WAVE_FORMAT_PCM */
  200.     wlshort(ft, ft->info.channels);
  201.     wllong(ft, (long)ft->info.rate);    /* SamplesPerSec */
  202.                     /* Average Bytes/sec */
  203.     wllong(ft, ((long)ft->info.rate * ft->info.channels * samsize + 7) / 8);
  204.                     /* nBlockAlign */
  205.     wlshort(ft, (ft->info.channels * samsize + 7) / 8);
  206.     wlshort(ft, samsize);        /* BitsPerSample */
  207.     
  208.     fputs("data", ft->fp);
  209.     wllong(ft, datasize);        /* data chunk size: FIXUP(40) */
  210. }
  211.  
  212. wavwrite(ft, buf, len) 
  213. ft_t ft;
  214. long *buf, len;
  215. {
  216.     wav_t    wav = (wav_t) ft->priv;
  217.  
  218.     wav->samples += len;
  219.     rawwrite(ft, buf, len);
  220. }
  221.  
  222. void
  223. wavstopwrite(ft) 
  224. ft_t ft;
  225. {
  226.     /* All samples are already written out. */
  227.     /* If file header needs fixing up, for example it needs the */
  228.      /* the number of samples in a field, seek back and write them here. */
  229.     if (!ft->seekable)
  230.         return;
  231.     if (fseek(ft->fp, 0L, 0) != 0)
  232.         fail("Sorry, can't rewind output file to rewrite .wav header.");
  233.     wavwritehdr(ft);
  234. }
  235.